#include "filterview.h"

FilterView::FilterView():search_key(0),nocontent(true),has_searched(false)
{
    Gtk::Image *searchicon = Gtk::manage (new Gtk::Image (Gtk::Stock::FIND, Gtk::ICON_SIZE_BUTTON));
    search.set_icon (Sexy::ICON_ENTRY_PRIMARY, searchicon);
    search.signal_changed().connect(sigc::mem_fun(*this,&FilterView::onSearchChanged));
    search.signal_icon_pressed().connect_notify(sigc::mem_fun(*this,&FilterView::onIconClicked));
    //search.signal_editing_done().connect();
    search.signal_grab_focus().connect(sigc::mem_fun(*this,&FilterView::onEntryIn));
    search.signal_focus_out_event().connect(sigc::mem_fun(*this,&FilterView::onEntryOut));
    search.signal_activate().connect(sigc::mem_fun(*this,&FilterView::onEntryActivate));
    set_spacing (6);
    pack_end(search,false,false,0);
    m_leftbutton.set_label("<");
    m_rightbutton.set_label(">");
    m_rightbutton.signal_clicked().connect(sigc::mem_fun(*this,&FilterView::onRightClick));
    m_leftbutton.signal_clicked().connect(sigc::mem_fun(*this,&FilterView::onLeftClick));
    pack_end(m_rightbutton,false,false,0);
    pack_start(m_leftbutton,false,false,0);

    Gtk::Adjustment * ha = manage (new Gtk::Adjustment (0.0, 0.0, 1000,30));
    Gtk::Adjustment * va = manage (new Gtk::Adjustment (0, 0, 0));
    Gtk::Viewport * viewport = manage (new Gtk::Viewport(*ha, *va));
    m_scrolledwindow = manage (new Gtk::ScrolledWindow ());
    m_scrolledwindow->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
    m_scrolledwindow->set_shadow_type(Gtk::SHADOW_NONE);

    viewport->add(m_filterbox);
    m_scrolledwindow->add(*viewport);
    pack_start(*m_scrolledwindow);
    Gtk::Requisition req=search.size_request();
    set_size_request(0,req.height+2);
    search.show();
    show_all();
    Gtk::RadioButtonGroup group;
    iconpopup.items().push_back(Gtk::Menu_Helpers::RadioMenuElem(group,"Name contain", sigc::bind(sigc::mem_fun(*this, &FilterView::onChoiceChanged),0 ) ));
    iconpopup.items().push_back(Gtk::Menu_Helpers::RadioMenuElem(group,"Abstract contain", sigc::bind(sigc::mem_fun(*this, &FilterView::onChoiceChanged),1) ));
    iconpopup.items().push_back(Gtk::Menu_Helpers::RadioMenuElem(group,"Publisher contain", sigc::bind(sigc::mem_fun(*this, &FilterView::onChoiceChanged),2)) );
    iconpopup.items().push_back(Gtk::Menu_Helpers::RadioMenuElem(group,"Tag contain", sigc::bind(sigc::mem_fun(*this, &FilterView::onChoiceChanged),3)));
    //iconpopup.items().push_back(Gtk::Menu_Helpers::SeparatorElem() );
    //iconpopup.items().push_back(Gtk::Menu_Helpers::MenuElem("Advance search...", sigc::mem_fun(*this, &FilterView::onAdvanceSearch) ) );
    iconpopup.accelerate(*this);
    initEntry();
    std::vector<Gtk::TargetEntry> targets;
    targets.push_back( Gtk::TargetEntry("FILTER-ID") );
    drag_source_set(targets);
    targets.push_back(Gtk::TargetEntry("DOCUMENT-ID"));
    targets.push_back(Gtk::TargetEntry("WRITING-ID"));
    targets.push_back(Gtk::TargetEntry("PUBLISHER-ID"));
    targets.push_back(Gtk::TargetEntry("TAG-ID"));
    targets.push_back(Gtk::TargetEntry("SEARCH-ID"));
    drag_dest_set(targets);
    signal_drag_data_received().connect(sigc::mem_fun(*this,&FilterView::onDataReceived) );
}

FilterView::~FilterView()
{
}
void FilterView::initEntry()
{
    switch(search_key)
    {
    case 1://categories
        if (nocontent) search.set_text("Abstract contain");
        break;
    case 2://themes
        if (nocontent) search.set_text("Publisher contain");
        break;
    case 3://tags
        if (nocontent) search.set_text("Tag contain");
        break;
    default://0, document name
        if (nocontent) search.set_text("Name contain");
    }
}
void FilterView::set_documents(sdms::documents* doc)
{
    mydoc=doc;
}

void FilterView::set_docview(DocView* dv)
{
    docview=dv;
}

void FilterView::onSearchChanged()
{
    if (nocontent) return;
    Gdk::Color yellowish ("#f7f7be");
    Gdk::Color black ("#000000");

    bool hasclearbutton =search.get_icon (Sexy::ICON_ENTRY_SECONDARY);

    if (!search.get_text ().empty())
    {
        search.modify_base (Gtk::STATE_NORMAL, yellowish);
        search.modify_text (Gtk::STATE_NORMAL, black);
        if (!hasclearbutton) search.add_clear_button ();
    }
    else
    {
        search.unset_base (Gtk::STATE_NORMAL);
        search.unset_text (Gtk::STATE_NORMAL);
        if (hasclearbutton)  search.set_icon (Sexy::ICON_ENTRY_SECONDARY, NULL);
    }
}
void FilterView::onIconClicked(Sexy::IconEntryPosition pos,int button)
{
    Gdk::Event event=Gdk::Event::get();
    if (pos==Sexy::ICON_ENTRY_PRIMARY)
    {
        iconpopup.popup(button,event.get_time());
        //std::cout<<"test iconclicked."<<std::endl;
    }
    else
    {
        //clear button
        std::cout<<"clear search"<<std::endl;
        if (has_searched)
        {
            nocontent=true;
            has_searched=false;
            //恢复到所有文档？
            //docview->update();
            update();
            initEntry();
            search.unset_base (Gtk::STATE_NORMAL);
            search.unset_text (Gtk::STATE_NORMAL);
        }
    }
}
void FilterView::onChoiceChanged(unsigned int key)
{
    search_key=key;
    initEntry();
}
//高级搜索，弹出搜索对话框
void FilterView::onAdvanceSearch()
{
    std::cout<<"advance search"<<std::endl;
}
void FilterView::onEntryIn()
{
    if (nocontent)
    {
        search.set_text("");
        nocontent=false;
    }
}
bool FilterView::onEntryOut(GdkEventFocus* event)
{
    if (search.get_text().empty())
    {
        nocontent=true;
        initEntry();
    }
    return true;
}
//生成搜索
void FilterView::onEntryActivate()
{
    //std::cout<<"test activate"<<std::endl;
    if (search.get_text().empty()) return;

    sdms::PublisherFilter tf;
    sdms::TagFilter gf;
    sdms::DocumentFilter df;
    sdms::AbstractFilter cf;
    switch(search_key)
    {
    case 1://Abstract
        cf.set_documents(mydoc);
        cf.set_name(search.get_text());
        cf.eval();
        docview->update(&cf);
        break;
    case 2://Publisher
        tf.set_documents(mydoc);
        tf.set_name(search.get_text());
        tf.eval();
        docview->update(&tf);
        break;
    case 3://tags
        gf.set_documents(mydoc);
        gf.set_name(search.get_text());
        gf.eval();
        docview->update(&gf);
        break;
    default://0, document name
        df.set_documents(mydoc);
        df.set_name(search.get_text());
        df.eval();
        docview->update(&df);
        break;
    }
    has_searched=true;
}

void FilterView::onDataReceived(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,const Gtk::SelectionData& sel, guint, guint time)
{
    std::cout<<sel.get_data_type()<<std::endl;
    std::cerr << "onData: got '" << sel.get_data_as_string () << "'\n";
    if (!resultfilter.empty())
    {
        //Gtk::Label* orlabel= Gtk::manage(new Gtk::Label(" OR "));
        //pack_start(*orlabel,Gtk::PACK_SHRINK);
        //orlabel->show();
        //还应该添加一个清除选择的按钮
    }
    std::string seldata=sel.get_data_as_string();
    std::vector<std::string> ids=utils::explode(seldata,",");
    std::cout<<"in filterview, receive:"<<seldata<<std::endl;
    std::cout<<sel.get_data_type()<<std::endl;
    if (sel.get_data_type()=="TAG-ID")
    {
        for (int i=0; i<ids.size(); i++)
        {
            sdms::TagFilter tf;
            tf.set_documents(mydoc);
            tf.set_id(utils::fromString<int>(ids[i]));
            tf.eval();
            add(tf);
        }
    }
    else if (sel.get_data_type()=="WRITING-ID")
    {
        for (int i=0; i<ids.size(); i++)
        {
            sdms::WritingFilter tf;
            tf.set_documents(mydoc);
            tf.set_id(utils::fromString<int>(ids[i]));
            tf.eval();
            add(tf);
        }
    }
    else if (sel.get_data_type()=="PUBLISHER-ID")
    {
        for (int i=0; i<ids.size(); i++)
        {
            sdms::PublisherFilter tf;
            tf.set_documents(mydoc);
            tf.set_name(ids[i]);
            tf.eval();
            add(tf);
        }
    }
    //docview->update(&resultfilter);
}
void FilterView::clear()
{
    resultfilter.clear();
    m_filterbox.hide_all();
    myfilters.clear();
    m_filterbox.show();
    m_scrolledwindow->show();
    search.show();
    show();
}
void FilterView::add(const sdms::PublisherFilter& tf)
{
    resultfilter=(resultfilter||tf);
    myfilters.push_back(tf);
    //std::vector<sdms::category> tags=mydoc->getcategory(utils::fromString<int>(ids[i]));
    FilterButton* fb=Gtk::manage(new FilterButton());
    fb->set_filter(tf);
    fb->set_text(tf.get_name());
    fb->set_icontype(FilterButton::PUBLISHER);
    fb->set_size_request(-1,-1);
    m_filterbox.pack_start(*fb,Gtk::PACK_SHRINK);
    fb->signal_closed().connect(sigc::mem_fun(*this,&FilterView::remove));
    fb->show();
    m_filterbox.show();
    docview->update(&resultfilter);
}
void FilterView::add(const sdms::WritingFilter& tf)
{
    resultfilter=(resultfilter||tf);
    myfilters.push_back(tf);
    FilterButton* fb=Gtk::manage(new FilterButton());
    if (tf.get_name().empty())
    {
        std::vector<sdms::writing> ws=mydoc->getwriting(tf.get_id());
        fb->set_text(ws[0].name);
    }
    else
        fb->set_text(tf.get_name());
    fb->set_filter(tf);
    fb->set_icontype(FilterButton::WRITING);
    fb->set_size_request(-1,-1);
    m_filterbox.pack_start(*fb,Gtk::PACK_SHRINK);
    fb->signal_closed().connect(sigc::mem_fun(*this,&FilterView::remove));
    fb->show();
    m_filterbox.show();
    docview->update(&resultfilter);
}
void FilterView::add(const sdms::TagFilter& tf)
{
    resultfilter=(resultfilter||tf);
    myfilters.push_back(tf);
    //std::vector<sdms::tag> tags=mydoc->gettag(utils::fromString<int>(ids[i]));
    //Gtk::Label* lab=Gtk::manage(new Gtk::Label("Tag:"+tags[0].name));
    FilterButton* fb=Gtk::manage(new FilterButton());
    if (tf.get_name().empty())
    {
        std::vector<sdms::tag> ws=mydoc->gettag(tf.get_id());
        fb->set_text(ws[0].name);
    }
    else
        fb->set_text(tf.get_name());
    fb->set_filter(tf);
    fb->set_icontype(FilterButton::TAG);
    fb->set_size_request(-1,-1);
    m_filterbox.pack_start(*fb,Gtk::PACK_SHRINK);
    fb->signal_closed().connect(sigc::mem_fun(*this,&FilterView::remove));
    fb->show();
    m_filterbox.show();
    docview->update(&resultfilter);
}
void FilterView::add(const sdms::Filter& tf)
{
    resultfilter=(resultfilter||tf);
    myfilters.push_back(tf);
    FilterButton* fb=Gtk::manage(new FilterButton());
    if (tf.get_name().empty())
    {
        fb->set_text("unkown");
    }
    else
        fb->set_text(tf.get_name());
    fb->set_filter(tf);
    fb->set_size_request(-1,-1);
    fb->set_icontype(FilterButton::FILTER);
    m_filterbox.pack_start(*fb,Gtk::PACK_SHRINK);
    fb->signal_closed().connect(sigc::mem_fun(*this,&FilterView::remove));
    fb->show();
    m_filterbox.show();
    docview->update(&resultfilter);
}
void FilterView::update()
{
    std::cout<<"update filterview"<<std::endl;
    resultfilter.clear();
    std::cout<<resultfilter.tostring()<<std::endl;
    for(int i=0; i<myfilters.size(); i++)
    {
        //only support OR relationship now.
        //The AND relationship is in TODO list.
        resultfilter=(resultfilter||myfilters[i]);
    }
    docview->update(&resultfilter);
}
void FilterView::remove(std::string sql)
{
    std::cout<<"remove filterview"<<std::endl;
    std::cout<<sql<<std::endl;
    for(std::vector<sdms::Filter>::iterator i=myfilters.begin(); i!=myfilters.end(); i++)
    {
        if (i->get_sql()==sql)
        {
            myfilters.erase(i);
            break;
        }
    }
    update();
}
void FilterView::onRightClick()
{
    double v=m_scrolledwindow->get_hadjustment()->get_value()+m_scrolledwindow->get_hadjustment()->get_step_increment();
    if (v>=m_scrolledwindow->get_hadjustment()->get_lower() &&v<=m_scrolledwindow->get_hadjustment()->get_upper()-m_scrolledwindow->get_hadjustment()->get_page_size())
    {
        m_scrolledwindow->get_hadjustment()->set_value(v);
        m_scrolledwindow->get_hadjustment()->value_changed();
        m_scrolledwindow->get_hadjustment()->changed();
    }
}
void FilterView::onLeftClick()
{
    double v=m_scrolledwindow->get_hadjustment()->get_value()-m_scrolledwindow->get_hadjustment()->get_step_increment();
    if (v>=m_scrolledwindow->get_hadjustment()->get_lower() && v<=m_scrolledwindow->get_hadjustment()->get_upper()-m_scrolledwindow->get_hadjustment()->get_page_size())
    {
        m_scrolledwindow->get_hadjustment()->set_value(v);
        m_scrolledwindow->get_hadjustment()->value_changed();
        m_scrolledwindow->get_hadjustment()->changed();
    }
}
